package view;

import boardGenerator.Pair;
import controllers.SudokuController;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import org.netbeans.lib.awtextra.AbsoluteConstraints;
import org.netbeans.lib.awtextra.AbsoluteLayout;

/**
 * Clase Vista Sudoku Alternativa
 */
public class AlternativeView extends IMainView {    
    private JFrame jfWindow;
    private Celda[][] matriz;
    private JLabel time;
    private JLabel puntos;
    private JLabel numRestantes;
    private Color color1 = Color.black;
    private Color color2 = Color.DARK_GRAY;    
    private Color fontColor = Color.white;
    private Color wrongCell = Color.RED;
    private Color fontColorNoEditable = Color.CYAN;    
    private Color correctColor = Color.GREEN;
    private Color selectedColor = Color.GREEN;
    private Color caretColor = selectedColor;
    private Color fontColorPista = Color.magenta;
    private JRadioButton radHard;
    private JRadioButton radModerate;
    private JRadioButton radEasy;
    private JTextField player = new JTextField(17);
        
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem10;
    private javax.swing.JMenuItem jMenuItem11;
    private javax.swing.JMenuItem jMenuItem12;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem5;
    private javax.swing.JMenuItem jMenuItem6;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JMenuItem jMenuItem8;
    private javax.swing.JMenuItem jMenuItem9;
    private javax.swing.JMenuItem jMenuItem60;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    
    /*Listener Para el movimiento y las teclas*/
    private KeyListener keyList1 = new KeyAdapter() {public void keyTyped(KeyEvent evt) {Teclea(evt);}};
    private KeyListener keyList2 = new KeyAdapter() {public void keyPressed(KeyEvent evt) {Mover(evt);}};
    private FocusListener focusList1 = new FocusAdapter() {public void focusGained(FocusEvent evt) {textFieldFocusGained(evt);}};
    private FocusListener focusList2 = new FocusAdapter() {public void focusLost(FocusEvent evt) {textFieldFocusLost(evt);}};
    private MouseListener mouseList1 = new MouseAdapter() {public void mouseClicked(MouseEvent evt) {formMouseClicked(evt);}};
    

    /**
     * Constructor de la Clase Vista Alternativa
     * Inicializa todos los componenetes
     */
    public AlternativeView(){
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e){
            e.printStackTrace();
        }
        jfWindow = new JFrame();
        jfWindow.setMinimumSize(new Dimension(300,300));        
        //Segun la dimension de la pantalla (resolucion) tamaño y posicion de la ventana default
        Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
        Point framePos=new Point((int)(screenSize.width)/2-250,(int)(screenSize.height)/2-300);
        jfWindow.setLocation(framePos);
        //Dimension frameSize = new Dimension((int)(screenSize.width),(int)(screenSize.height));
        //jfWindow.setBounds(0,0,frameSize.width,frameSize.height);
        //Renombro el cartel
        jfWindow.setTitle("BigSudoku");
        jfWindow.setIconImage(Toolkit.getDefaultToolkit().getImage(IMainView.class.getResource("/resources/sudoku-icon.png")));
        //Configuro los Contenedores de la Ventana
        Container container = jfWindow.getContentPane();
        setupMainContainer(container);
        //Configuro las caracteristicas de la Ventana
        jfWindow.pack();
        jfWindow.setVisible(true);
        jfWindow.setResizable(false);
        jfWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        for (Component comp :jfWindow.getComponents()){
            comp.addMouseListener(new MouseAdapter() {public void mouseClicked(MouseEvent evt) {formMouseClicked(evt);}});
        }        
    }
    
    /**
     * Inicializa el Contenedor principal del JFrame
     * @param container 
     */
    private void setupMainContainer(Container container){
        menuBar();   
        container.setLayout(new BorderLayout());
        container.add(informacion(),BorderLayout.PAGE_START);
        container.add(tablero(),BorderLayout.CENTER);
    }
    
    /**
     * Panel Informacion de la Partida
     * @return 
     */
    private JPanel informacion(){
        JPanel info = new JPanel();
        JPanel datos = new JPanel();
        datos.setLayout(new GridLayout(1,6,0,0));
        datos.setPreferredSize(new Dimension(400, 40));
        datos.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Partida", TitledBorder.CENTER, TitledBorder.TOP, null, null));
        
        JLabel timeText = new JLabel("Tiempo: ");
        timeText.setFont(new java.awt.Font("Tahoma", 0, 15));
        time = new JLabel();
        time.setFont(new java.awt.Font("Tahoma", 0, 15));
        time.setText("00:00:00");        
        timeText.setHorizontalAlignment(JLabel.RIGHT);
        datos.add(timeText);
        datos.add(time);
        
        JLabel numText = new JLabel("Faltan: ");
        numText.setFont(new java.awt.Font("Tahoma", 0, 15));
        numRestantes = new JLabel();
        numRestantes.setFont(new java.awt.Font("Tahoma", 0, 15));
        numRestantes.setText("81");
        numText.setHorizontalAlignment(JLabel.RIGHT);
        datos.add(numText);
        datos.add(numRestantes);
        
        JLabel puntText = new JLabel("Puntos: ");
        puntText.setFont(new java.awt.Font("Tahoma", 0, 15));
        puntos = new JLabel();
        puntos.setFont(new java.awt.Font("Tahoma", 0, 15));
        puntos.setText("0");
        puntos.setHorizontalAlignment(JLabel.LEFT);
        puntText.setHorizontalAlignment(JLabel.RIGHT);
        datos.add(puntText);
        datos.add(puntos);
        
        info.add(datos);
        return info;
    }
    
    /**
     * Barra de Menus Principal
     */
    private void menuBar(){        
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem10 = new javax.swing.JMenuItem();
        jMenuItem6 = new javax.swing.JMenuItem();
        jMenuItem60 = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem3 = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem8 = new javax.swing.JMenuItem();
        jMenuItem9 = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jMenuItem5 = new javax.swing.JMenuItem();
        jMenuItem7 = new javax.swing.JMenuItem();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenu4 = new javax.swing.JMenu();
        jMenuItem11 = new javax.swing.JMenuItem();
        jMenuItem12 = new javax.swing.JMenuItem();
        
        jMenu1.setText("Archivo");

        jMenuItem10.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem10.setText("Cambiar Vista");
        jMenuItem10.addActionListener(SudokuController.getInstance());
        jMenuItem10.setActionCommand("OTHER_VIEW");
        jMenu1.add(jMenuItem10);

        jMenuItem6.setText("Top Ten");
        jMenuItem6.addActionListener(SudokuController.getInstance());
        jMenuItem6.setActionCommand("TOP_TEN");
        jMenu1.add(jMenuItem6);
        
        jMenuItem60.setText("Reglas Sudoku");
        jMenuItem60.addActionListener(SudokuController.getInstance());
        jMenuItem60.setActionCommand("RULES");
        jMenu1.add(jMenuItem60);
        
        jMenu1.add(jSeparator2);

        jMenuItem2.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem2.setText("Salir");        
        jMenuItem2.addActionListener(SudokuController.getInstance());
        jMenuItem2.setActionCommand("EXIT");
        jMenu1.add(jMenuItem2);
        jMenuBar1.add(jMenu1);

        jMenu2.setText("Editar");

        jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem3.setText("Preferencias");
        jMenuItem3.addActionListener(SudokuController.getInstance());
        jMenuItem3.setActionCommand("CONFIG");
        jMenu2.add(jMenuItem3);
        jMenuBar1.add(jMenu2);

        jMenu3.setText("Partida");

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem1.setText("Nueva Partida");
        jMenuItem1.addActionListener(SudokuController.getInstance());
        jMenuItem1.setActionCommand("START_GAME");
        jMenu3.add(jMenuItem1);

        jMenuItem8.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem8.setText("Reiniciar");
        jMenuItem8.addActionListener(SudokuController.getInstance());
        jMenuItem8.setActionCommand("RESET_GAME");
        jMenu3.add(jMenuItem8);

        jMenuItem9.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem9.setText("Finalizar");
        jMenuItem9.addActionListener(SudokuController.getInstance());
        jMenuItem9.setActionCommand("STOP_GAME");
        jMenu3.add(jMenuItem9);
        jMenu3.add(jSeparator1);

        jMenuItem5.setText("Verificar");
        jMenuItem5.addActionListener(SudokuController.getInstance());
        jMenuItem5.setActionCommand("CHECK_GAME");
        jMenu3.add(jMenuItem5);

        jMenuItem7.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem7.setText("Pista");
        jMenuItem7.addActionListener(SudokuController.getInstance());
        jMenuItem7.setActionCommand("GET_HINT");
        jMenu3.add(jMenuItem7);

        jMenuItem4.setText("Resolver");
        jMenuItem4.addActionListener(SudokuController.getInstance());
        jMenuItem4.setActionCommand("SOLVE_GAME");
        jMenu3.add(jMenuItem4);

        jMenuBar1.add(jMenu3);

        jMenu4.setText("Ayuda");

        jMenuItem11.setText("Sudoku Online");
        jMenuItem11.addActionListener(SudokuController.getInstance());
        jMenuItem11.setActionCommand("SUDOKU_WEB");
        jMenu4.add(jMenuItem11);

        jMenuItem12.setText("Acerda De");
        jMenu4.add(jMenuItem12);

        jMenuBar1.add(jMenu4);

        this.jfWindow.setJMenuBar(jMenuBar1);
    }
    
    /**
     * Crea el Panel Tablero
     * @return 
     */
    private JPanel tablero(){
        JPanel superior = new JPanel();
        superior.setLayout(new AbsoluteLayout());
        JPanel tablero = new JPanel();
        Dimension dim = new Dimension(420,420);
        tablero.setMaximumSize(dim);
        tablero.setPreferredSize(dim);
        tablero.setSize(dim);        
        tablero.setLayout(new GridLayout(9,9,2,2));        
        crearMatriz();
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                tablero.add(matriz[i][j]);
            }            
        }
        superior.add(tablero,new AbsoluteConstraints(10, 10, -1, -1));        
        return superior;
    }
    
    /**
     * Crea la matriz de Celdas JTextFileds
     */
    private void crearMatriz(){
        matriz = new Celda[9][9];
        Celda tmp;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                tmp = new Celda();
                tmp.setColumns(1);
                tmp.setFont(new java.awt.Font("Tahoma", 0, 18));
                tmp.setForeground(fontColor);                
                tmp.setHorizontalAlignment(javax.swing.JTextField.CENTER);
                tmp.setBorder(javax.swing.BorderFactory.createEtchedBorder());
                tmp.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
                tmp.setMargin(new java.awt.Insets(0, 0, 0, 0));
                tmp.setMaximumSize(new java.awt.Dimension(4, 4));
                tmp.setMinimumSize(new java.awt.Dimension(4, 4));
                tmp.setPreferredSize(new java.awt.Dimension(4, 4));
                tmp.setSize(4,4);
                tmp.setInputVerifier(new IntegerInput());                
                tmp.setEditable(false);
                tmp.setEnabled(false);                
                tmp.setCursor(new Cursor(Cursor.HAND_CURSOR));
                tmp.setCaretColor(caretColor);
                tmp.setKeymap(null);
                tmp.setFil(i);
                tmp.setCol(j);
                if (((i<3 || i>5)&&(j<3||j>5)) || (i>2 && i<6 && j>2 && j<6)){
                    tmp.setNormalColor(color2);
                } else {
                    tmp.setNormalColor(color1);
                }
                tmp.setWrong(false);
                matriz[i][j] = tmp;
            }
        }
    }
    
    /**
     * habilita los botones de la vista principal
     * @param var 
     */
    public void habilitarControles(boolean var){        
            /**
             * No Aplica a la vista Alternativa
             */
    }

    /**
     * Habilita la interaccion con el tablero
     */
    public void habilitarTablero(){        
        this.normalizeBoard();
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                Celda tmp = matriz[i][j];
                tmp.setEditable(true);
                tmp.setEnabled(true);
                tmp.addKeyListener(this.keyList1);
                tmp.addKeyListener(this.keyList2);
                tmp.addFocusListener(this.focusList1);
                tmp.addFocusListener(this.focusList2);
                tmp.addMouseListener(this.mouseList1);                
            }
        }
    }
    
    /**
     * deshabilita la interaccion con el tablero
     */
    public void deshabilitarTablero(){
        for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    Celda tmp = matriz[i][j];
                    tmp.setEditable(false);
                    tmp.setEnabled(false);
                    tmp.removeKeyListener(this.keyList1);
                    tmp.removeKeyListener(this.keyList2);
                    tmp.removeFocusListener(this.focusList1);
                    tmp.removeFocusListener(this.focusList2);
                    tmp.removeMouseListener(this.mouseList1);
                }
            }
    }
    
    /**
     * Refresca el contador de tiempo
     * @param time 
     */
    public void refreshTime(String time){
        this.time.setText(time);
    }
    
    /**
     * Refresca el contador de puntuacion
     * @param punt 
     */
    public void refreshPuntuacion(String punt){
        this.puntos.setText(punt);
    }
        
    /**
     * Refresca el contador de numeros restantes
     * @param num 
     */
    public void refreshContador(String num){
        this.numRestantes.setText(num);
    }
    
    /**
     * Establece la matriz del tablero
     * @param param matriz de enteros de 9x9
     */
    public void setMatriz(int[][] param){
        this.normalizeBoard();
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                setNum(i,j,param[i][j]);
            }            
        }        
    }
    
    /**
     * Obtiene toda la Matriz del Tablero
     * @return  matriz de enteros de 9x9
     */
    public int[][] getMatriz(){
        int[][] result = new int[9][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                result[i][j] = getNum(i,j);
            }            
        }        
        return result;
    }
    
    /**
     * Establece un valor para una celda del tablero dado
     * @pre   -1<fil<9 and -1<col<9
     * @param fil pos de fila
     * @param col pos de columna
     * @param value valor
     */
    public void setNum(int fil,int col,int value){
        if (value == 0){            
            matriz[fil][col].setText("");
            matriz[fil][col].setEnabled(true);
            matriz[fil][col].setEditable(true);
            matriz[fil][col].setFont(new java.awt.Font("Tahoma", 1, 18));
        } else {            
            matriz[fil][col].setText(String.valueOf(value));
            matriz[fil][col].setEnabled(false);
            matriz[fil][col].setEditable(false);
            matriz[fil][col].setFont(new java.awt.Font("Tahoma", 2, 16));
            matriz[fil][col].setDisabledTextColor(fontColorNoEditable);
        }
    }
    
    /**
     * Pone un valor en el tablero como si fuese
     * una pista, en otro color y no editable
     * @param fil posicicon fila
     * @param col posicion columna
     * @param value numero a ingresar
     */
    public void setPista(int fil,int col,int value){
        matriz[fil][col].setText(String.valueOf(value));
        matriz[fil][col].setEnabled(false);
        matriz[fil][col].setEditable(false);
        matriz[fil][col].setDisabledTextColor(fontColorPista);
    }
    
    /**
     * Establece una celda como incorrecta
     * @param fil
     * @param col 
     */    
    public void setWrong(int fil,int col){        
        matriz[fil][col].setBackground(wrongCell);
        matriz[fil][col].setWrong(true);
    }
    
    /**
     * Establece una celda como normal
     * @param fil
     * @param col 
     */    
    public void setNormal(int fil,int col){
        matriz[fil][col].setBackground(matriz[fil][col].getNormalColor());
        matriz[fil][col].setWrong(false);
    }
    
    /**
     * Establece una celda como correcta
     * @param fil
     * @param col 
     */    
    public void setCorrect(int fil,int col){
        matriz[fil][col].setForeground(correctColor);
    }
    
    
    /**
     * Obtiene el valor de una celda. Si este valor no es
     * numerico devuelve un -1
     * @pre   -1<fil<9 and -1<col<9
     * @param fil pos de fila
     * @param col pos de columna
     * @return 
     */
    public int getNum(int fil,int col){
        try {
            return Integer.valueOf(matriz[fil][col].getText());
        } catch (Exception e){
            return 0;
        }
    }
    
    /**
     * Obtiene el nombre del jugador actual     * 
     * @return string con el nombre
     */
    public String getPlayerName(){
        return SudokuController.getInstance().getConfiguration().getNamePlayer();
    }
    
    /**
     * Establece el nombre del jugador actual
     * @param nombre
     */
    public void setPlayerName(String nomb){
        this.player.setText(nomb);
    }
    
    /**
     * Muestra un mensage de advertencia por pantalla
     */
    public void showWarningMessage(String msg){
        JOptionPane.showMessageDialog(null,msg," Advertencia",JOptionPane.WARNING_MESSAGE);
    }
    
    /**
     * Muesta un mensage de informacion por pantalla
     */
    public void showInfoMessage(String msg){
        JOptionPane.showMessageDialog(null,msg," Informacion",JOptionPane.INFORMATION_MESSAGE);
    }
    
    /**
     * Muestra un mensaje de confirmacion por pantalla
     * @return true/false segun desicion 
     */
    public boolean showConfirmationMessage(String msg){
        int i = JOptionPane.showConfirmDialog(null, msg, " Confirmacion", JOptionPane.YES_NO_OPTION);        
        return (i == JOptionPane.YES_OPTION);
    }
    
    /**
     * Cierra la ventana actual
     */
    public void dispose(){
        this.jfWindow.dispose();
    }
    
    /**
     * evita la interaccion con la ventana actual
     * @param val 
     */
    public void disable(Boolean val) {
        this.jfWindow.setEnabled(!val);
    }
    
    /**
     * Reclama el foco hacia la ventana principal
     * y la trae al frente
     */
    public void requestFocus(){
        this.jfWindow.requestFocus();        
        this.jfWindow.toFront();
    }
    
    /**
     * Verifica que solo ponga numeros entre 0 y 9
     */
    private class IntegerInput extends InputVerifier{        
        @Override
        public boolean verify(JComponent input) {
            JTextField tmp = (JTextField)input;
            String text = tmp.getText();
            int num;
            if (text.length()==0){
                return true;
            } else {
                try {
                    num = Integer.parseInt(text);
                } catch (Exception e) {
                    tmp.setText("");
                    return false;
                }
                if (num<0 || num >9){
                    tmp.setText("");
                    return false;
                } else {
                    return true;
                }
            }
        }
    }
    
    /**
     * Punta el Tablero (fondo) con los colores normales
     */    
    private void normalizeBoard(){
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                matriz[i][j].setBackground(matriz[i][j].getNormalColor());
            }
        }
    }
    
    /**
     * Evita poner otra cosa que no sea un numero del 1..9
     * @param evt 
     */
    private void Teclea(KeyEvent evt){
        Celda tmp = (Celda) evt.getComponent();
        switch (evt.getKeyChar()) {
            case '1': tmp.setText("1");insert(tmp,1);break;
            case '2': tmp.setText("2");insert(tmp,2);break;
            case '3': tmp.setText("3");insert(tmp,3);break;
            case '4': tmp.setText("4");insert(tmp,4);break;
            case '5': tmp.setText("5");insert(tmp,5);break;
            case '6': tmp.setText("6");insert(tmp,6);break;
            case '7': tmp.setText("7");insert(tmp,7);break;
            case '8': tmp.setText("8");insert(tmp,8);break;
            case '9': tmp.setText("9");insert(tmp,9);break;            
        }
    }
    
    /**
     * Inserta un valor en la celda y notifica al observador
     * @param field
     * @param value 
     */
    private void insert(Celda field, int value){
        field.setWrong(false);
        Pair<Pair<Integer,Integer>,Integer> tmp = new Pair<Pair<Integer,Integer>,Integer>();
        Pair<Integer,Integer> pos = new Pair(field.getFil(),field.getCol());
        tmp.setFirst(pos);tmp.setSecond(value);        
        setChanged();
        notifyObservers(tmp);     
    }

    
    /**
     * Permite desplazarce en la grilla con las 
     * teclas de direccion y borrar elementos con supr y delete
     * @param evt 
     */
    private void Mover(KeyEvent evt){
        int dir = evt.getKeyCode();        
        Celda actual = (Celda) evt.getComponent();
        int fil = actual.getFil();
        int col = actual.getCol();     
        switch (dir){
            case 40: moverAbajo(fil,col);break;
            case 38: moverArriba(fil,col);break;
            case 37: moverIzquierda(fil,col);break;
            case 39: moverDerecha(fil,col);break;
            case 8: case 127: /*Borra valor*/
                        insert(actual,0);
                        actual.setText("");break;
        }        
    }
    
    /**
     * Mueve el foco una fila abajo
     * @param fil
     * @param col 
     */
    private void moverAbajo(int fil, int col){
        if (fil+1<9){
            while (!matriz[fil+1][col].isEnabled() && fil+1<9){
                fil++;
                if (fil+1>8) fil = -1;
            }
        }
        if (fil+1>8){
           moverAbajo(-1,col);
        } else {
            matriz[fil+1][col].requestFocus();
        }
    }
    
    /**
     * Mueve el foco una celda a la derecha
     * @param fil
     * @param col 
     */
    private void moverDerecha(int fil, int col){
        if (col+1<9){
            while (!matriz[fil][col+1].isEnabled() && col+1<9){
                col++;
                if (col+1>8) col = -1;
            }
        }
        if (col+1>8){
           moverDerecha(fil,-1);
        } else {
            matriz[fil][col+1].requestFocus();
        }
    }
    
    /**
     * Mueve el foco una fila arriba
     * @param fil
     * @param col 
     */
    private void moverArriba(int fil, int col){
        if (fil-1>-1){
            while (!matriz[fil-1][col].isEnabled() && fil-1>-1){
                fil--;
                if (fil-1<0) fil = 9;
            }
        }
        if (fil-1<0){
           moverArriba(9,col);
        } else {
            matriz[fil-1][col].requestFocus();
        }
    }
    
    /**
     * Mueve el foco una celda a la derecha
     * @param fil
     * @param col 
     */
    private void moverIzquierda(int fil, int col){
        if (col-1>-1){
            while (!matriz[fil][col-1].isEnabled() && col-1>-1){
                col--;
                if (col-1<0) col = 9;
            }
        }
        if (col-1<0){
           moverIzquierda(fil,9);
        } else {
            matriz[fil][col-1].requestFocus();
        }
    }
    
    /**
     * Cuando la celda gana el foco se pinta de otro color
     * @param evt 
     */
    private void textFieldFocusGained(FocusEvent evt){        
        ((Celda)evt.getSource()).setBackground(selectedColor);
    }
    
    /**
     * Cuando la celda pierde el foco recupera color original
     * @param evt 
     */
    private void textFieldFocusLost(FocusEvent evt){
        Celda tmp = (Celda)evt.getSource();
        if (tmp.isWrong()) 
            tmp.setBackground(wrongCell);
        else
            tmp.setBackground(tmp.getNormalColor());
    }
    
    /**
     * Cuando hago clic derecho quito el foco actual
     * @param evt 
     */
    private void formMouseClicked(java.awt.event.MouseEvent evt) {
        if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK){
                jfWindow.requestFocus();
        }
    }    
}


